/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package infoplaces2;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author Andre Alvarado
 */
public class CubicPanoramicImage extends PlanarPanoramicImage {

//    CubicPanoramicImage(source: PanoramicImage)
//    CubicPanoramicImage(RenderedImage left, RenderedImage front, RenderedImage right, RenderedImage back, RenderedImage top, RenderedImage bottom)
//    fetch(x: double, y: double, z: double): RGBColor
//    fetch(azimuth: double, zenith: double): RGBColor
    public CubicPanoramicImage(EquirectangularPanoramicImage source) throws IOException { //source no caso eh uma EquirectangularPanoramicImage...posso fazer assim?
        super(makeImageArray(source));
//        super.images = source.processImageFile();
        //ArrayList<RenderedImage> images = source.processImageFile();
        //CubicPanoramicImage cubic = new CubicPanoramicImage(images.get(0), images.get(1), images.get(2), images.get(3), null, null); //objeto cubic inutil!!!!!!!!
    }

    public CubicPanoramicImage(RenderedImage left, RenderedImage front, RenderedImage right, RenderedImage back, RenderedImage top, RenderedImage bottom) {
        super(makeImageArray(left, front, right, back, top, bottom));
    }

    //TODO:
    private static ArrayList<RenderedImage> makeImageArray(PanoramicImage source) {
        /*
         BufferedImage left = null; // = new BufferedImage(...);
         //TODO Calcular left a partir de source.

         BufferedImage front = null; // = new BufferedImage(...);
         //TODO Calcular front a partir de source.

         BufferedImage right = null; // = new BufferedImage(...);
         //TODO Calcular right a partir de source.

         BufferedImage back = null; // = new BufferedImage(...);
         //TODO Calcular back a partir de source.

         BufferedImage top = null; // = new BufferedImage(...);
         //TODO Calcular top a partir de source.

         BufferedImage bottom = null; // = new BufferedImage(...);
         //TODO Calcular bottom a partir de source.

         return makeImageArray(left, front, right, back, top, bottom);
         */
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    private static ArrayList<RenderedImage> makeImageArray(EquirectangularPanoramicImage source) throws IOException {

        final String format = "jpg";
        // The following can be overriden/set by the indicated command line arguments
        final int overlap = 1;           	  // -overlap
        final String interpolation = "lanczos2";   // -interpolation (lanczos2, bilinear, nearest-neighbor)

        RenderedImage equi = source.getImage(0);
        ArrayList<BufferedImage> saida = new ArrayList<>();

        int equiWidth = equi.getWidth();
        int equiHeight = equi.getHeight();

//        if (equiWidth != equiHeight * 2) {
            int equiData[][] = new int[equiHeight][equiWidth];
            new ImageTo2DIntArrayExtractor(equiData, (Image) equi).doit();

            double fov; // horizontal field of view
           
            double r = equiWidth / (2D * Math.PI);
            double y = (Math.tan(Math.PI / 4D) * r + overlap);
            fov = Math.atan(y / r) * 180 / Math.PI * 2;
            int rectWidth = (int) (y * 2);
            int rectHeight = rectWidth;

            Boolean bilinear;
            Boolean lanczos2;
            if (interpolation == "lanczos2") {
                lanczos2 = true;
                bilinear = false;
            } else if (interpolation == "bilinear") {
                lanczos2 = false;
                bilinear = true;
            } else if (interpolation == "nearest-neighbor") {
                lanczos2 = false;
                bilinear = false;
            } else {
                lanczos2 = true;
                bilinear = false;
            }

            int rectData[];
            double pitch;
            double yaw;
            BufferedImage output;

            Equi2Rect.initForIntArray2D(equiData);

            yaw = 0;
            pitch = 0;
            rectData = Equi2Rect.extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
            output = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
            //setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) 
            output.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
            saida.add(output);
//            Panorama.salvarPano(output, "1.png");

            yaw = 90;
            pitch = 0;
            rectData = Equi2Rect.extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
            output = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
            output.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
            saida.add(output);

            yaw = 180;
            pitch = 0;
            rectData = Equi2Rect.extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
            output = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
            output.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
            saida.add(output);

            yaw = 270;
            pitch = 0;
            rectData = Equi2Rect.extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
            output = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
            output.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
            saida.add(output);

        BufferedImage top = null; // = new BufferedImage(...);
        //TODO Calcular top a partir de source.

        BufferedImage bottom = null; // = new BufferedImage(...);
        //TODO Calcular bottom a partir de source.

//        }
        return makeImageArray(saida.get(0), saida.get(1), saida.get(2), saida.get(3), top, bottom);
    }

    private static ArrayList<RenderedImage> makeImageArray(RenderedImage left, RenderedImage front, RenderedImage right, RenderedImage back, RenderedImage top, RenderedImage bottom) {
        ArrayList<RenderedImage> result = new ArrayList<>();
        result.add(left);
        result.add(front);
        result.add(right);
        result.add(back);
        result.add(top);
        result.add(bottom);

        //preciso passar esse array para ser tratado de diferentes formas quando chamada a classe abstrata PanoramicImage
        return result;
    }

    @Override
    public int fetch(double x, double y, double z) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public int fetch(double azimuth, double zenith) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    
}

class FileListFilter implements FilenameFilter {

    private Vector<String> extensions;

    public FileListFilter(Vector<String> extensions) {
        this.extensions = extensions;
    }

    public boolean accept(File directory, String filename) {
        if (extensions != null) {
            Iterator<String> itr = extensions.iterator();
            while (itr.hasNext()) {
                String ext = (String) itr.next();
                if (filename.endsWith('.' + ext)) {
                    return true;
                }
            }
        }
        return false;
    }
}

    //TODO:
//    private static ArrayList<RenderedImage> makeImageArray(EquirectangularPanoramicImage source) throws IOException {
//
//        BufferedImage left , front, right, back, top, bottom;
//        RenderedImage image = source.getImage(0);
//
//        int equiWidth = image.getWidth();
//        int equiHeight = image.getHeight();
//
////        if (equiWidth != equiHeight * 2) {
//            int equiData[][] = new int[equiHeight][equiWidth];
//            new ImageTo2DIntArrayExtractor(equiData, (Image) image).doit();
//
//            double fov; // horizontal field of view
//
//            double r = equiWidth / (2D * Math.PI);
//            double y = (Math.tan(Math.PI / 4D) * r + overlap);
//            fov = Math.atan(y / r) * 180 / Math.PI * 2;
//            int rectWidth = (int) (y * 2);
//            int rectHeight = rectWidth;
//
//            boolean bilinear;
//            boolean lanczos2;
//            if (interpolation == InterpolationType.LANCZOS2) {
//                lanczos2 = true;
//                bilinear = false;
//            } else if (interpolation == InterpolationType.BILINEAR) {
//                lanczos2 = false;
//                bilinear = true;
//            } else if (interpolation == InterpolationType.NEAREST) {
//                lanczos2 = false;
//                bilinear = false;
//            } else {
//                lanczos2 = true;
//                bilinear = false;
//            }
//
//            int rectData[];
//            double pitch;
//            double yaw;
//            
//            init();
//            initForIntArray2D(equiData);
//
//            yaw = 0;
//            pitch = 0;
//            rectData = extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
//            left = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
//            left.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
//
//            yaw = 90;
//            pitch = 0;
//            rectData = extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
//            front = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
//            front.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
//
//            yaw = 180;
//            pitch = 0;
//            rectData = extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
//            right = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
//            right.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
//
//            yaw = 270;
//            pitch = 0;
//            rectData = extractRectilinear(yaw, pitch, fov, equiData, rectWidth, rectHeight, equiWidth, bilinear, lanczos2);
//            back = new BufferedImage(rectWidth, rectHeight, BufferedImage.TYPE_INT_RGB);
//            back.setRGB(0, 0, rectWidth, rectHeight, rectData, 0, rectWidth);
//
//            top = null; // = new BufferedImage(...);
//            //TODO Calcular top a partir de source.
//
//            bottom = null; // = new BufferedImage(...);
//            //TODO Calcular bottom a partir de source.
//            
//        return makeImageArray(left, front, right, back, top, bottom);
//    }
